package com.example.demo.auth;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public final class TokenUtil {

    public static void main(String[] args) {
        String token = createToken(AuthConstants.SECRET_TOKEN_KEY, "1",
                new String[] {"HR", "BPO", "Purchase"},
                new String[] {"Manager", "Operator", "Tester"},
                new String[] {"read"});
        System.out.println(token);
        System.out.println(validateToken(token, AuthConstants.SECRET_TOKEN_KEY));

        Map<String, Object> map = decodeToken(token);
        System.out.println(map.get("sessionId"));
        String groups[] = (String[]) map.get("groups");
        if(groups != null) {
            for(String g: groups) {
                System.out.println(g);
            }
        }


    }

    public static String createToken(String signKey, String sessionId) {
        return createToken(signKey, sessionId, null, null, null);
    }


    public static String createToken(String signKey, String sessionId, String [] groups, String [] roles, String [] permissions) {
        String token = null;
        Map<String,Object> header=new HashMap<>();
        header.put("typ","JWT");
        header.put("alg","HS256");
        try {
            long now = System.currentTimeMillis();
            long exp = now + 12 * 3600 * 1000;
            token = JWT.create().withHeader(header).withAudience(sessionId, "2")
                    .withArrayClaim("groups", groups)
                    .withArrayClaim("roles", roles)
                    .withArrayClaim("permissions", permissions)
                    .withIssuedAt(new Date(now))
                    .withExpiresAt(new Date(exp))
                    .sign(Algorithm.HMAC256(signKey));
        } catch (Exception e) {
            // ignore
        }
        return token;
    }

    public static boolean validateToken(String token, String signKey) {
        try {
            JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(signKey)).build();
            jwtVerifier.verify(token);
        } catch (JWTVerificationException e) {
            // ignore
            return false;
        }
        return true;
    }

    public static Map<String, Object> decodeToken(String token) {
        DecodedJWT jwt = JWT.decode(token);
        Map<String, Object> map = new HashMap<>();
        List<String> list = jwt.getAudience();
        if(list != null && list.size() > 0) {
            String sessionId = jwt.getAudience().get(0);
            map.put("sessionId", sessionId);
        }

        Claim roles = jwt.getClaim("roles");
        if(!roles.isNull()) {
            map.put("roles", roles.asArray(String.class));
        }
        Claim groups = jwt.getClaim("groups");
        if(!groups.isNull()) {
            map.put("groups", groups.asArray(String.class));
        }
        Claim permissions = jwt.getClaim("permissions");
        if(!permissions.isNull()) {
            map.put("permissions", permissions.asArray(String.class));
        }
        return map;
    }

    public static Date getFutureDate(long secs) {
        long now = System.currentTimeMillis();
        now += secs * 1000;
        return new Date(now);
    }
}
